package net.neptech.service.ars;

import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.*;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import net.neptech.config.RedisConfig;
import net.neptech.entity.SpeechText;
import net.neptech.websocket.SubtitleWebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
public class RealTimeASRService {

    @Value("${aliyun.asr.app-key}")
    private String appKey;

    @Value("${aliyun.ak.id}")
    private String accessKeyId;

    @Value("${aliyun.ak.secret}")
    private String accessKeySecret;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    private NlsClient client;
    private final ConcurrentHashMap<String, SpeechTranscriber> transcriberMap = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() throws Exception {
        try {
            client = new NlsClient("wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1", getAccessToken());
            log.info("✅ 阿里云 ASR 客户端初始化成功");
        } catch (Exception e) {
            log.error("ASR 客户端初始化失败", e);
            throw e;
        }
    }

    @PreDestroy
    public void shutdown() {
        if (client != null) {
            client.shutdown();
            log.info("🛑 ASR 客户端已关闭");
        }
    }

    private String getAccessToken() throws Exception {
        com.alibaba.nls.client.AccessToken accessToken = new com.alibaba.nls.client.AccessToken(accessKeyId, accessKeySecret);
        accessToken.apply();
        return accessToken.getToken();
    }

public void startTranscription(String asrKey, String doctorName) {
    try {
        SpeechTranscriberListener listener = createListener(asrKey, doctorName);
        SpeechTranscriber transcriber = new SpeechTranscriber(client, listener);
        transcriber.setAppKey(appKey);
        transcriber.setFormat(InputFormatEnum.PCM);
        transcriber.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
        // ✅ 打开中间结果，前端可以更早看到长句的持续输出
        transcriber.setEnableIntermediateResult(true);
        transcriber.setEnablePunctuation(true);
        transcriber.setEnableITN(false);

        transcriber.start();

        transcriberMap.put(asrKey, transcriber);
        log.info("🟢 启动实时语音识别: {}", asrKey);
    } catch (Exception e) {
        log.error("启动语音识别失败: " + asrKey, e);
    }
}


    public void sendAudioData(String asrKey, byte[] audioData) {
     SpeechTranscriber transcriber = transcriberMap.get(asrKey);
    try {
                 if (transcriber == null) {
                         log.warn("🔁 transcriber 丢失，尝试重建: {}", asrKey);
                                 startTranscription(asrKey, "未知医生");
                         transcriber = transcriberMap.get(asrKey);
                     }
                 if (transcriber != null) {
                         transcriber.send(audioData, audioData.length);
                     }
             } catch (Exception e) {
                 log.error("发送音频数据失败: " + asrKey, e);
             }
    }

     public void stopTranscription(String asrKey) {
        SpeechTranscriber transcriber = transcriberMap.remove(asrKey);
        if (transcriber != null) {
            try {
                transcriber.stop();
                transcriber.close();
                log.info("⏹️ 会诊 {} 的语音识别已停止", asrKey);
            } catch (Exception e) {
                log.error("停止语音识别失败", e);
            }
        }

     }

     private SpeechTranscriberListener createListener(String asrKey, String doctorName) {
        return new SpeechTranscriberListener() {

            @Override
            public void onTranscriberStart(SpeechTranscriberResponse response) {
                log.info("🟢 语音识别通道已建立: task_id={}", response.getTaskId());
            }

            @Override
            public void onSentenceBegin(SpeechTranscriberResponse response) {
                // 可选：句子开始
                log.debug("▶️ 句子开始: task_id={}", response.getTaskId());
            }

            @Override
            public void onTranscriptionResultChange(SpeechTranscriberResponse response) {
                String partial = response.getTransSentenceText();
                if (partial != null && !partial.isEmpty()) {
                    String conferenceId = asrKey.split(":", 2)[0];
                    SubtitleWebSocket.pushSubtitleEx(conferenceId, doctorName, partial, true); // ✅ partial
                }
            }

            @Override
            public void onSentenceEnd(SpeechTranscriberResponse response) {
                String sentence = response.getTransSentenceText();
                if (sentence != null && !sentence.trim().isEmpty()) {
                    log.info("✅ 完整句子 [{}]: {}", doctorName, sentence);
                    String conferenceId = asrKey.split(":", 2)[0];

                    // 1) 继续推实时字幕
                    SubtitleWebSocket.pushSubtitleEx(conferenceId, doctorName, sentence, false);

                    // 2) 写入 Redis 列表
                    try {
                        String userId = "unknown";
                        String[] parts = asrKey.split(":", 2);
                        if (parts.length > 1) userId = parts[1];

                        String redisKey = "meeting:transcripts:" + conferenceId;
                        SpeechText st = new SpeechText(userId, doctorName, "doctor",
                                sentence, System.currentTimeMillis());
                        redisTemplate.opsForList().rightPush(redisKey, st);

                        // 可选：限制列表长度（只保留最近 5000 条）
                        Long size = redisTemplate.opsForList().size(redisKey);
                        if (size != null && size > 5000) {
                            long start = Math.max(0, size - 5000);
                            redisTemplate.opsForList().trim(redisKey, start, -1);
                        }
                    } catch (Exception e) {
                        log.error("写入 Redis 字幕失败", e);
                    }
                }
            }



            @Override
            public void onTranscriptionComplete(SpeechTranscriberResponse response) {
                log.info("🏁 语音识别会话完成: task_id={}", response.getTaskId());
            }

            @Override
            public void onFail(SpeechTranscriberResponse response) {
                log.error("❌ 客户端异常: task_id={}, status={}, msg={}",
                        response.getTaskId(), response.getStatus(), response.getStatusText());
            }
        };
    }
}